package com.blog.cmrpersonalblog.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.blog.cmrpersonalblog.config.RankingConfig;
import com.blog.cmrpersonalblog.dto.ranking.requset.RankingRequest;
import com.blog.cmrpersonalblog.dto.ranking.respnose.RankingItemResponse;
import com.blog.cmrpersonalblog.dto.ranking.respnose.RankingResponse;
import com.blog.cmrpersonalblog.entity.Article;
import com.blog.cmrpersonalblog.entity.ArticleCategory;
import com.blog.cmrpersonalblog.entity.SysUser;
import com.blog.cmrpersonalblog.entity.UserCollect;
import com.blog.cmrpersonalblog.entity.UserStats;
import com.blog.cmrpersonalblog.enums.RankingDimension;
import com.blog.cmrpersonalblog.enums.RankingType;
import com.blog.cmrpersonalblog.mapper.ArticleMapper;
import com.blog.cmrpersonalblog.mapper.CategoryMapper;
import com.blog.cmrpersonalblog.mapper.SysUserMapper;
import com.blog.cmrpersonalblog.mapper.UserCollectMapper;
import com.blog.cmrpersonalblog.mapper.UserFollowMapper;
import com.blog.cmrpersonalblog.mapper.UserStatsMapper;
import com.blog.cmrpersonalblog.service.HeatScoreCalculator;
import com.blog.cmrpersonalblog.service.RankingService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 排行榜服务实现（重构版）
 * 支持文章榜、作者榜、收藏榜
 * 支持综合榜和分类榜
 */
@Slf4j
@Service
@ConditionalOnProperty(name = "ranking.redis-enabled", havingValue = "true", matchIfMissing = true)
public class RankingServiceImpl implements RankingService {
    
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    @Resource
    private ArticleMapper articleMapper;
    
    @Resource
    private SysUserMapper sysUserMapper;
    
    @Resource
    private UserStatsMapper userStatsMapper;
    
    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private UserCollectMapper userCollectMapper;

    @Resource
    private UserFollowMapper userFollowMapper;

    @Resource
    private HeatScoreCalculator heatScoreCalculator;

    @Resource
    private RankingConfig rankingConfig;
    
    // Redis Key 前缀
    private static final String RANKING_KEY_PREFIX = "ranking:";
    private static final String RANKING_HISTORY_KEY_PREFIX = "ranking:history:";
    private static final String RANKING_UPDATE_TIME_KEY = "ranking:update_time";
    private static final int DEFAULT_PAGE_SIZE = 20;
    
    @Override
    public RankingResponse getRanking(RankingRequest request) {
        try {
            // 参数验证
            RankingType rankingType = RankingType.valueOf(request.getRankingType());
            RankingDimension dimension = RankingDimension.valueOf(request.getDimension());
            
            // 分类榜必须提供分类ID
            if (dimension == RankingDimension.CATEGORY && request.getCategoryId() == null) {
                throw new IllegalArgumentException("分类榜必须提供分类ID");
            }
            
            // 构建Redis Key
            String redisKey = buildRankingKey(rankingType, dimension, request.getCategoryId());
            
            // 查询榜单数据
            List<RankingItemResponse> items;
            long total;
            
            if (Boolean.TRUE.equals(request.getTopOnly())) {
                // TOP N查询
                int topN = request.getTopN() != null ? request.getTopN().intValue() : rankingConfig.getMaxSize();
                items = getTopNFromRedis(redisKey, topN, rankingType);
                total = items.size();
            } else {
                // 分页查询
                long current = request.getCurrent() != null ? request.getCurrent() : 1L;
                long size = request.getSize() != null ? request.getSize() : DEFAULT_PAGE_SIZE;
                
                // 计算分页参数
                long start = (current - 1) * size;
                long end = start + size - 1;
                
                // 从Redis获取分页数据
                items = getRangeFromRedis(redisKey, start, end, rankingType);
                
                // 获取总数
                Long totalCount = redisTemplate.opsForZSet().zCard(redisKey);
                total = totalCount != null ? totalCount : 0L;
            }
            
            // 获取当前用户ID（如果已登录）
            Long currentUserId = getCurrentUserId();

            // 填充详细信息
            fillRankingDetails(items, rankingType, currentUserId);

            // 计算排名变化
            calculateRankChanges(items, rankingType);

            // 构建响应（使用 PageResult 的分页字段）
            RankingResponse response = RankingResponse.create(
                items,
                total,
                request.getSafeCurrent(),
                request.getSafeSize()
            );

            // 设置元数据
            response.setRankingType(request.getRankingType());
            response.setDimension(request.getDimension());
            response.setCategoryId(request.getCategoryId());
            response.setUpdateTime(getLastUpdateTime());
            response.setNextUpdateTime(getNextUpdateTime());

            return response;
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            log.error("查询榜单失败", e);
            throw new RuntimeException("查询榜单失败：" + e.getMessage());
        }
    }
    
    @Override
    public void refreshAllRankings() {
        log.info("开始刷新所有榜单...");
        long startTime = System.currentTimeMillis();
        
        try {
            // 刷新文章榜
            refreshArticleRankings();
            
            // 刷新作者榜
            refreshAuthorRankings();
            
            // 刷新收藏榜
            refreshCollectionRankings();
            
            // 更新刷新时间
            redisTemplate.opsForValue().set(RANKING_UPDATE_TIME_KEY, LocalDateTime.now());
            
            long endTime = System.currentTimeMillis();
            log.info("所有榜单刷新完成，耗时: {}ms", endTime - startTime);
        } catch (Exception e) {
            log.error("刷新所有榜单失败", e);
            throw new RuntimeException("刷新所有榜单失败：" + e.getMessage());
        }
    }
    
    @Override
    public void refreshRanking(RankingType rankingType, RankingDimension dimension, Long categoryId) {
        log.info("刷新榜单: type={}, dimension={}, categoryId={}", rankingType, dimension, categoryId);
        
        try {
            String redisKey = buildRankingKey(rankingType, dimension, categoryId);
            
            // 清空现有榜单
            redisTemplate.delete(redisKey);
            
            // 根据类型刷新
            switch (rankingType) {
                case ARTICLE:
                    refreshArticleRanking(dimension, categoryId, redisKey);
                    break;
                case AUTHOR:
                    refreshAuthorRanking(dimension, categoryId, redisKey);
                    break;
                case COLLECTION:
                    refreshCollectionRanking(dimension, categoryId, redisKey);
                    break;
                default:
                    throw new IllegalArgumentException("不支持的榜单类型: " + rankingType);
            }
            
            log.info("榜单刷新完成: {}", redisKey);
        } catch (Exception e) {
            log.error("刷新榜单失败", e);
            throw new RuntimeException("刷新榜单失败：" + e.getMessage());
        }
    }
    
    @Override
    public void updateRankingItem(RankingType rankingType, Long targetId) {
        log.info("更新榜单项: type={}, targetId={}", rankingType, targetId);
        
        try {
            switch (rankingType) {
                case ARTICLE:
                    updateArticleRanking(targetId);
                    break;
                case AUTHOR:
                    updateAuthorRanking(targetId);
                    break;
                case COLLECTION:
                    updateCollectionRanking(targetId);
                    break;
                default:
                    throw new IllegalArgumentException("不支持的榜单类型: " + rankingType);
            }
        } catch (Exception e) {
            log.error("更新榜单项失败", e);
            throw new RuntimeException("更新榜单项失败：" + e.getMessage());
        }
    }
    
    @Override
    public void removeFromRanking(RankingType rankingType, Long targetId) {
        log.info("从榜单移除: type={}, targetId={}", rankingType, targetId);
        
        try {
            // 获取所有相关的榜单Key
            String pattern = RANKING_KEY_PREFIX + rankingType.getCode().toLowerCase() + ":*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys != null && !keys.isEmpty()) {
                for (String key : keys) {
                    redisTemplate.opsForZSet().remove(key, targetId.toString());
                }
                log.info("已从{}个榜单中移除目标: {}", keys.size(), targetId);
            }
        } catch (Exception e) {
            log.error("从榜单移除失败", e);
            throw new RuntimeException("从榜单移除失败：" + e.getMessage());
        }
    }
    
    @Override
    public Long getRank(RankingType rankingType, RankingDimension dimension, Long targetId, Long categoryId) {
        try {
            String redisKey = buildRankingKey(rankingType, dimension, categoryId);
            Long rank = redisTemplate.opsForZSet().reverseRank(redisKey, targetId.toString());
            return rank != null ? rank + 1 : null; // Redis排名从0开始，转换为从1开始
        } catch (Exception e) {
            log.error("查询排名失败", e);
            return null;
        }
    }
    
    @Override
    public void clearAllRankings() {
        log.info("清空所有榜单");
        
        try {
            String pattern = RANKING_KEY_PREFIX + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("已清空{}个榜单", keys.size());
            }
        } catch (Exception e) {
            log.error("清空榜单失败", e);
            throw new RuntimeException("清空榜单失败：" + e.getMessage());
        }
    }
    
    @Override
    public RankingStatistics getStatistics() {
        RankingStatistics stats = new RankingStatistics();
        
        try {
            // 统计各类榜单数量
            long articleCount = countRankingsByType(RankingType.ARTICLE);
            long authorCount = countRankingsByType(RankingType.AUTHOR);
            long collectionCount = countRankingsByType(RankingType.COLLECTION);
            
            stats.setArticleRankingCount(articleCount);
            stats.setAuthorRankingCount(authorCount);
            stats.setCollectionRankingCount(collectionCount);
            stats.setTotalRankingCount(articleCount + authorCount + collectionCount);
            stats.setLastUpdateTime(getLastUpdateTime());
            
        } catch (Exception e) {
            log.error("获取榜单统计失败", e);
        }
        
        return stats;
    }
    
    @Override
    public LocalDateTime getNextUpdateTime() {
        // 根据配置计算下次更新时间
        RankingConfig.RefreshConfig refreshConfig = rankingConfig.getRefresh();
        LocalDateTime now = LocalDateTime.now();
        
        // 计算下一个刷新时间点
        LocalDateTime nextUpdate = now
                .plusDays(refreshConfig.getIntervalDays())
                .withHour(refreshConfig.getHour())
                .withMinute(refreshConfig.getMinute())
                .withSecond(0)
                .withNano(0);
        
        return nextUpdate;
    }
    
    // ==================== 私有辅助方法 ====================
    
    /**
     * 构建Redis Key
     */
    private String buildRankingKey(RankingType rankingType, RankingDimension dimension, Long categoryId) {
        StringBuilder key = new StringBuilder(RANKING_KEY_PREFIX);
        key.append(rankingType.getCode().toLowerCase());
        key.append(":");
        key.append(dimension.getCode().toLowerCase());

        if (dimension == RankingDimension.CATEGORY && categoryId != null) {
            key.append(":");
            key.append(categoryId);
        }

        return key.toString();
    }

    /**
     * 从Redis获取TOP N数据
     */
    private List<RankingItemResponse> getTopNFromRedis(String redisKey, int topN, RankingType rankingType) {
        Set<ZSetOperations.TypedTuple<Object>> tuples =
            redisTemplate.opsForZSet().reverseRangeWithScores(redisKey, 0, topN - 1);

        if (tuples == null || tuples.isEmpty()) {
            return new ArrayList<>();
        }

        List<RankingItemResponse> items = new ArrayList<>();
        int rank = 1;
        for (ZSetOperations.TypedTuple<Object> tuple : tuples) {
            RankingItemResponse item = new RankingItemResponse();
            item.setRank(rank++);
            item.setTargetId(Long.valueOf(tuple.getValue().toString()));
            // 将 Double 分数四舍五入转换为 Long
            item.setHeatScore(Math.round(tuple.getScore()));
            items.add(item);
        }

        return items;
    }

    /**
     * 从Redis获取范围数据
     */
    private List<RankingItemResponse> getRangeFromRedis(String redisKey, long start, long end, RankingType rankingType) {
        Set<ZSetOperations.TypedTuple<Object>> tuples =
            redisTemplate.opsForZSet().reverseRangeWithScores(redisKey, start, end);

        if (tuples == null || tuples.isEmpty()) {
            return new ArrayList<>();
        }

        List<RankingItemResponse> items = new ArrayList<>();
        int rank = (int) (start + 1);
        for (ZSetOperations.TypedTuple<Object> tuple : tuples) {
            RankingItemResponse item = new RankingItemResponse();
            item.setRank(rank++);
            item.setTargetId(Long.valueOf(tuple.getValue().toString()));
            // 将 Double 分数四舍五入转换为 Long
            item.setHeatScore(Math.round(tuple.getScore()));
            items.add(item);
        }

        return items;
    }

    /**
     * 获取当前登录用户ID
     */
    private Long getCurrentUserId() {
        try {
            if (StpUtil.isLogin()) {
                return StpUtil.getLoginIdAsLong();
            }
        } catch (Exception e) {
            log.debug("获取当前用户ID失败，用户未登录");
        }
        return null;
    }

    /**
     * 填充榜单详情
     */
    private void fillRankingDetails(List<RankingItemResponse> items, RankingType rankingType, Long currentUserId) {
        if (items == null || items.isEmpty()) {
            return;
        }

        switch (rankingType) {
            case ARTICLE:
                fillArticleDetails(items, currentUserId);
                break;
            case AUTHOR:
                fillAuthorDetails(items, currentUserId);
                break;
            case COLLECTION:
                fillCollectionDetails(items, currentUserId);
                break;
        }
    }

    /**
     * 计算排名变化
     */
    private void calculateRankChanges(List<RankingItemResponse> items, RankingType rankingType) {
        // TODO: 实现排名变化计算逻辑
        // 需要从历史榜单中获取上次排名，计算变化
        for (RankingItemResponse item : items) {
            item.setRankChange(0);
            item.setIsNew(false);
        }
    }

    /**
     * 刷新所有文章榜
     */
    private void refreshArticleRankings() {
        log.info("刷新文章榜...");

        // 刷新综合榜
        refreshArticleRanking(RankingDimension.OVERALL, null,
            buildRankingKey(RankingType.ARTICLE, RankingDimension.OVERALL, null));

        // 刷新各分类榜
        List<ArticleCategory> categories = categoryMapper.selectList(null);
        for (ArticleCategory category : categories) {
            refreshArticleRanking(RankingDimension.CATEGORY, category.getId(),
                buildRankingKey(RankingType.ARTICLE, RankingDimension.CATEGORY, category.getId()));
        }

        log.info("文章榜刷新完成，共刷新{}个榜单", categories.size() + 1);
    }

    /**
     * 刷新所有作者榜
     */
    private void refreshAuthorRankings() {
        log.info("刷新作者榜...");

        // 刷新综合榜
        refreshAuthorRanking(RankingDimension.OVERALL, null,
            buildRankingKey(RankingType.AUTHOR, RankingDimension.OVERALL, null));

        // 刷新各分类榜
        List<ArticleCategory> categories = categoryMapper.selectList(null);
        for (ArticleCategory category : categories) {
            refreshAuthorRanking(RankingDimension.CATEGORY, category.getId(),
                buildRankingKey(RankingType.AUTHOR, RankingDimension.CATEGORY, category.getId()));
        }

        log.info("作者榜刷新完成，共刷新{}个榜单", categories.size() + 1);
    }

    /**
     * 刷新所有收藏榜
     */
    private void refreshCollectionRankings() {
        log.info("刷新收藏榜...");

        // 刷新综合榜
        refreshCollectionRanking(RankingDimension.OVERALL, null,
            buildRankingKey(RankingType.COLLECTION, RankingDimension.OVERALL, null));

        // 刷新各分类榜
        List<ArticleCategory> categories = categoryMapper.selectList(null);
        for (ArticleCategory category : categories) {
            refreshCollectionRanking(RankingDimension.CATEGORY, category.getId(),
                buildRankingKey(RankingType.COLLECTION, RankingDimension.CATEGORY, category.getId()));
        }

        log.info("收藏榜刷新完成，共刷新{}个榜单", categories.size() + 1);
    }

    /**
     * 刷新单个文章榜
     */
    private void refreshArticleRanking(RankingDimension dimension, Long categoryId, String redisKey) {
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getStatus, 1); // 只统计已发布的文章

        if (dimension == RankingDimension.CATEGORY && categoryId != null) {
            wrapper.eq(Article::getCategoryId, categoryId);
        }

        List<Article> articles = articleMapper.selectList(wrapper);

        if (articles.isEmpty()) {
            log.debug("没有文章数据，跳过榜单刷新: {}", redisKey);
            return;
        }

        // 计算热度并添加到Redis
        for (Article article : articles) {
            Long heatScore = heatScoreCalculator.calculateArticleHeatScore(
                article.getViewCount(),
                article.getLikeCount(),
                article.getCollectCount(),
                article.getCommentCount(),
                article.getShareCount(),
                article.getPublishTime()
            );
            if (heatScore != null && heatScore > 0) {
                redisTemplate.opsForZSet().add(redisKey, article.getId().toString(), heatScore.doubleValue());
            }
        }

        // 裁剪到TOP N
        trimRanking(redisKey);

        log.debug("文章榜刷新完成: {}, 共{}篇文章", redisKey, articles.size());
    }

    /**
     * 刷新单个作者榜
     */
    private void refreshAuthorRanking(RankingDimension dimension, Long categoryId, String redisKey) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getStatus, 1); // 只统计正常状态的用户

        List<SysUser> users = sysUserMapper.selectList(wrapper);

        if (users.isEmpty()) {
            log.debug("没有用户数据，跳过榜单刷新: {}", redisKey);
            return;
        }

        // 计算作者影响力
        for (SysUser user : users) {
            // 如果是分类榜，只统计该分类下的文章
            Long influenceScore;
            if (dimension == RankingDimension.CATEGORY && categoryId != null) {
                influenceScore = calculateAuthorInfluenceByCategory(user.getUserId(), categoryId);
            } else {
                // 获取用户统计数据（修复：使用 user_id 字段查询而不是主键 id）
                UserStats stats = userStatsMapper.selectOne(
                    new LambdaQueryWrapper<UserStats>().eq(UserStats::getUserId, user.getUserId())
                );
                if (stats != null) {
                    influenceScore = heatScoreCalculator.calculateAuthorInfluenceScore(
                        stats.getFollowerCount(),
                        stats.getArticleCount(),
                        stats.getTotalViewCount() != null ? stats.getTotalViewCount().intValue() : 0,
                        stats.getTotalLikeCount(),
                        stats.getTotalCollectCount()
                    );
                } else {
                    influenceScore = 0L;
                }
            }

            if (influenceScore != null && influenceScore > 0) {
                redisTemplate.opsForZSet().add(redisKey, user.getUserId().toString(), influenceScore.doubleValue());
            }
        }

        // 裁剪到TOP N
        trimRanking(redisKey);

        log.debug("作者榜刷新完成: {}, 共{}位作者", redisKey, users.size());
    }

    /**
     * 刷新单个收藏榜
     */
    private void refreshCollectionRanking(RankingDimension dimension, Long categoryId, String redisKey) {
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getStatus, 1); // 只统计已发布的文章
        wrapper.orderByDesc(Article::getCollectCount);

        if (dimension == RankingDimension.CATEGORY && categoryId != null) {
            wrapper.eq(Article::getCategoryId, categoryId);
        }

        List<Article> articles = articleMapper.selectList(wrapper);

        if (articles.isEmpty()) {
            log.debug("没有文章数据，跳过榜单刷新: {}", redisKey);
            return;
        }

        // 按收藏数添加到Redis
        for (Article article : articles) {
            Integer collectCount = article.getCollectCount();
            if (collectCount != null && collectCount > 0) {
                redisTemplate.opsForZSet().add(redisKey, article.getId().toString(), collectCount.doubleValue());
            }
        }

        // 裁剪到TOP N
        trimRanking(redisKey);

        log.debug("收藏榜刷新完成: {}, 共{}篇文章", redisKey, articles.size());
    }

    /**
     * 更新文章榜项
     */
    private void updateArticleRanking(Long articleId) {
        Article article = articleMapper.selectById(articleId);
        if (article == null || article.getStatus() != 1) {
            log.warn("文章不存在或未发布，无法更新榜单: {}", articleId);
            return;
        }

        // 计算热度
        Long heatScore = heatScoreCalculator.calculateArticleHeatScore(
            article.getViewCount(),
            article.getLikeCount(),
            article.getCollectCount(),
            article.getCommentCount(),
            article.getShareCount(),
            article.getPublishTime()
        );

        // 更新综合榜
        String overallKey = buildRankingKey(RankingType.ARTICLE, RankingDimension.OVERALL, null);
        redisTemplate.opsForZSet().add(overallKey, articleId.toString(), heatScore.doubleValue());
        trimRanking(overallKey);

        // 更新分类榜
        if (article.getCategoryId() != null) {
            String categoryKey = buildRankingKey(RankingType.ARTICLE, RankingDimension.CATEGORY, article.getCategoryId());
            redisTemplate.opsForZSet().add(categoryKey, articleId.toString(), heatScore.doubleValue());
            trimRanking(categoryKey);
        }

        log.debug("文章榜项更新完成: articleId={}, heatScore={}", articleId, heatScore);
    }

    /**
     * 更新作者榜项
     */
    private void updateAuthorRanking(Long userId) {
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null || user.getStatus() != 1) {
            log.warn("用户不存在或状态异常，无法更新榜单: {}", userId);
            return;
        }

        // 获取用户统计数据（修复：使用 user_id 字段查询而不是主键 id）
        UserStats stats = userStatsMapper.selectOne(
            new LambdaQueryWrapper<UserStats>().eq(UserStats::getUserId, userId)
        );
        if (stats == null) {
            log.warn("用户统计数据不存在: {}", userId);
            return;
        }

        // 计算影响力
        Long influenceScore = heatScoreCalculator.calculateAuthorInfluenceScore(
            stats.getFollowerCount(),
            stats.getArticleCount(),
            stats.getTotalViewCount() != null ? stats.getTotalViewCount().intValue() : 0,
            stats.getTotalLikeCount(),
            stats.getTotalCollectCount()
        );

        // 更新综合榜
        String overallKey = buildRankingKey(RankingType.AUTHOR, RankingDimension.OVERALL, null);
        redisTemplate.opsForZSet().add(overallKey, userId.toString(), influenceScore.doubleValue());
        trimRanking(overallKey);

        // 更新各分类榜
        List<ArticleCategory> categories = categoryMapper.selectList(null);
        for (ArticleCategory category : categories) {
            Long categoryScore = calculateAuthorInfluenceByCategory(userId, category.getId());
            if (categoryScore != null && categoryScore > 0) {
                String categoryKey = buildRankingKey(RankingType.AUTHOR, RankingDimension.CATEGORY, category.getId());
                redisTemplate.opsForZSet().add(categoryKey, userId.toString(), categoryScore.doubleValue());
                trimRanking(categoryKey);
            }
        }

        log.debug("作者榜项更新完成: userId={}, influenceScore={}", userId, influenceScore);
    }

    /**
     * 更新收藏榜项
     */
    private void updateCollectionRanking(Long articleId) {
        Article article = articleMapper.selectById(articleId);
        if (article == null || article.getStatus() != 1) {
            log.warn("文章不存在或未发布，无法更新榜单: {}", articleId);
            return;
        }

        Integer collectCount = article.getCollectCount();
        if (collectCount == null || collectCount <= 0) {
            log.debug("文章收藏数为0，跳过更新: {}", articleId);
            return;
        }

        // 更新综合榜
        String overallKey = buildRankingKey(RankingType.COLLECTION, RankingDimension.OVERALL, null);
        redisTemplate.opsForZSet().add(overallKey, articleId.toString(), collectCount.doubleValue());
        trimRanking(overallKey);

        // 更新分类榜
        if (article.getCategoryId() != null) {
            String categoryKey = buildRankingKey(RankingType.COLLECTION, RankingDimension.CATEGORY, article.getCategoryId());
            redisTemplate.opsForZSet().add(categoryKey, articleId.toString(), collectCount.doubleValue());
            trimRanking(categoryKey);
        }

        log.debug("收藏榜项更新完成: articleId={}, collectCount={}", articleId, collectCount);
    }

    /**
     * 填充文章详情（优化版：批量查询）
     */
    private void fillArticleDetails(List<RankingItemResponse> items, Long currentUserId) {
        if (items == null || items.isEmpty()) {
            return;
        }

        // 批量查询文章
        List<Long> articleIds = items.stream()
            .map(RankingItemResponse::getTargetId)
            .collect(Collectors.toList());

        List<Article> articles = articleMapper.selectBatchIds(articleIds);
        Map<Long, Article> articleMap = articles.stream()
            .collect(Collectors.toMap(Article::getId, a -> a));

        // 收集所有作者ID和分类ID
        Set<Long> authorIds = new HashSet<>();
        Set<Long> categoryIds = new HashSet<>();
        for (Article article : articles) {
            if (article.getAuthorId() != null) {
                authorIds.add(article.getAuthorId());
            }
            if (article.getCategoryId() != null) {
                categoryIds.add(article.getCategoryId());
            }
        }

        // 批量查询作者信息
        Map<Long, SysUser> authorMap = new HashMap<>();
        if (!authorIds.isEmpty()) {
            List<SysUser> authors = sysUserMapper.selectBatchIds(authorIds);
            authorMap = authors.stream()
                .collect(Collectors.toMap(SysUser::getUserId, a -> a));
        }

        // 批量查询分类信息
        Map<Long, ArticleCategory> categoryMap = new HashMap<>();
        if (!categoryIds.isEmpty()) {
            List<ArticleCategory> categories = categoryMapper.selectBatchIds(new ArrayList<>(categoryIds));
            categoryMap = categories.stream()
                .collect(Collectors.toMap(ArticleCategory::getId, c -> c));
        }

        // 批量查询用户收藏状态（如果用户已登录）
        Set<Long> collectedArticleIds = new HashSet<>();
        if (currentUserId != null) {
            try {
                List<UserCollect> collects = userCollectMapper.selectBatchUserCollectStatus(currentUserId, articleIds);
                collectedArticleIds = collects.stream()
                    .filter(UserCollect::isCollected)
                    .map(UserCollect::getArticleId)
                    .collect(Collectors.toSet());
            } catch (Exception e) {
                log.warn("批量查询用户收藏状态失败: userId={}", currentUserId, e);
            }
        }

        // 填充详情
        for (RankingItemResponse item : items) {
            Article article = articleMap.get(item.getTargetId());
            if (article != null) {
                item.setTitle(article.getTitle());
                item.setCoverImage(article.getCoverImage());
                item.setViewCount(article.getViewCount());
                item.setLikeCount(article.getLikeCount());
                item.setCollectCount(article.getCollectCount());
                item.setCommentCount(article.getCommentCount());
                item.setShareCount(article.getShareCount());
                item.setPublishTime(article.getPublishTime());
                item.setCategoryId(article.getCategoryId());

                // 填充作者信息
                if (article.getAuthorId() != null) {
                    SysUser author = authorMap.get(article.getAuthorId());
                    if (author != null) {
                        item.setAuthorId(author.getUserId());
                        item.setSubtitle(author.getNickName());
                        item.setAuthorNickName(author.getNickName());
                        item.setAuthorAvatar(author.getAvatar());
                    }
                }

                // 填充分类名称
                if (article.getCategoryId() != null) {
                    ArticleCategory category = categoryMap.get(article.getCategoryId());
                    if (category != null) {
                        item.setCategoryName(category.getName());
                    }
                }

                // 填充用户收藏状态
                if (currentUserId != null) {
                    item.setIsCollected(collectedArticleIds.contains(article.getId()));
                }
            }
        }
    }

    /**
     * 填充作者详情（优化版：批量查询）
     */
    private void fillAuthorDetails(List<RankingItemResponse> items, Long currentUserId) {
        if (items == null || items.isEmpty()) {
            return;
        }

        // 批量查询用户
        List<Long> userIds = items.stream()
            .map(RankingItemResponse::getTargetId)
            .collect(Collectors.toList());

        List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
        Map<Long, SysUser> userMap = users.stream()
            .collect(Collectors.toMap(SysUser::getUserId, u -> u));

        // 批量查询用户统计信息（修复：使用 user_id 字段查询而不是主键 id）
        List<UserStats> statsList = userStatsMapper.selectList(
            new LambdaQueryWrapper<UserStats>().in(UserStats::getUserId, userIds)
        );
        Map<Long, UserStats> statsMap = statsList.stream()
            .collect(Collectors.toMap(UserStats::getUserId, s -> s));

        // 批量查询用户关注状态（如果用户已登录）
        Set<Long> followedUserIds = new HashSet<>();
        if (currentUserId != null) {
            try {
                List<Long> followedIds = userFollowMapper.selectBatchFollowingStatus(currentUserId, userIds);
                followedUserIds = new HashSet<>(followedIds);
            } catch (Exception e) {
                log.warn("批量查询用户关注状态失败: userId={}", currentUserId, e);
            }
        }

        // 填充详情
        for (RankingItemResponse item : items) {
            SysUser user = userMap.get(item.getTargetId());
            if (user != null) {
                item.setTitle(user.getNickName());
                item.setSubtitle(user.getSignature());
                item.setAvatar(user.getAvatar());
                item.setAuthorId(user.getUserId());
                item.setAuthorNickName(user.getNickName());
                item.setAuthorAvatar(user.getAvatar());

                // 填充统计信息
                UserStats stats = statsMap.get(user.getUserId());
                if (stats != null) {
                    item.setFansCount(stats.getFollowerCount());
                    item.setArticleCount(stats.getArticleCount());
                    item.setViewCount(stats.getTotalViewCount() != null ? stats.getTotalViewCount().intValue() : 0);
                    item.setLikeCount(stats.getTotalLikeCount());
                    item.setCollectCount(stats.getTotalCollectCount());
                }

                // 填充用户关注状态
                if (currentUserId != null) {
                    item.setIsFollowed(followedUserIds.contains(user.getUserId()));
                }
            }
        }
    }

    /**
     * 填充收藏榜详情（复用文章详情）
     */
    private void fillCollectionDetails(List<RankingItemResponse> items, Long currentUserId) {
        fillArticleDetails(items, currentUserId);
    }

    /**
     * 裁剪榜单到TOP N
     */
    private void trimRanking(String redisKey) {
        Long size = redisTemplate.opsForZSet().zCard(redisKey);
        if (size != null && size > rankingConfig.getMaxSize()) {
            // 移除分数最低的元素
            redisTemplate.opsForZSet().removeRange(redisKey, 0, size - rankingConfig.getMaxSize() - 1);
        }
    }

    /**
     * 统计指定类型的榜单数量
     */
    private long countRankingsByType(RankingType rankingType) {
        String pattern = RANKING_KEY_PREFIX + rankingType.getCode().toLowerCase() + ":*";
        Set<String> keys = redisTemplate.keys(pattern);

        if (keys == null || keys.isEmpty()) {
            return 0;
        }

        long total = 0;
        for (String key : keys) {
            Long count = redisTemplate.opsForZSet().zCard(key);
            total += (count != null ? count : 0);
        }

        return total;
    }

    /**
     * 获取最后更新时间
     */
    private LocalDateTime getLastUpdateTime() {
        Object time = redisTemplate.opsForValue().get(RANKING_UPDATE_TIME_KEY);
        if (time instanceof LocalDateTime) {
            return (LocalDateTime) time;
        }
        return null;
    }

    /**
     * 计算作者在指定分类下的影响力
     */
    private Long calculateAuthorInfluenceByCategory(Long userId, Long categoryId) {
        // 查询该作者在该分类下的文章
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getAuthorId, userId);
        wrapper.eq(Article::getCategoryId, categoryId);
        wrapper.eq(Article::getStatus, 1);

        List<Article> articles = articleMapper.selectList(wrapper);

        if (articles.isEmpty()) {
            return 0L;
        }

        // 统计该分类下的数据
        int totalViewCount = 0;
        int totalLikeCount = 0;
        int totalCollectCount = 0;

        for (Article article : articles) {
            totalViewCount += (article.getViewCount() != null ? article.getViewCount() : 0);
            totalLikeCount += (article.getLikeCount() != null ? article.getLikeCount() : 0);
            totalCollectCount += (article.getCollectCount() != null ? article.getCollectCount() : 0);
        }

        // 获取粉丝数（修复：使用 user_id 字段查询而不是主键 id）
        UserStats stats = userStatsMapper.selectOne(
            new LambdaQueryWrapper<UserStats>().eq(UserStats::getUserId, userId)
        );
        int fansCount = (stats != null && stats.getFollowerCount() != null) ? stats.getFollowerCount() : 0;

        // 计算影响力
        return heatScoreCalculator.calculateAuthorInfluenceScore(
            fansCount,
            articles.size(),
            totalViewCount,
            totalLikeCount,
            totalCollectCount
        );
    }
}

